// 套接字  实现断开重连；

#include <func.h>

int main(int argc, char *argv[])
{
  ARGS_CHECK(argc, 3);
  // 创建流；
  int sfd = socket(AF_INET, SOCK_STREAM, 0); // 创建一个流
  ERROR_CHECK(sfd, -1, "socket");
  // 创建一个结构体(ipv4类型的),并且初始化这个结构体

  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = inet_addr(argv[1]);
  addr.sin_port = htons(atoi(argv[2]));
  int optval = 1;
  int ret = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)); // 不需要那个waittime
  ERROR_CHECK(ret, -1, "setsockopt");
  // 这是一个服务器所以需要bind(绑定ip锁定端口)listen(半连接 ,全连接) accept(会返回一个新的流)

  ret = bind(sfd, (struct sockaddr *)&addr, sizeof(addr));
  ERROR_CHECK(ret, -1, "bind");
  ret = listen(sfd, 10);
  ERROR_CHECK(ret, -1, "listen");
  // 需要创建一个新的套接字（流）
  // int netfd = accept(sfd, NULL, NULL);
  // ERROR_CHECK(netfd, -1, "netfd");

  char buf[4096] = {0};
  fd_set rdset;      // 单纯的保存监听集合
  fd_set monitorSet; // 使用一个单独的监听集合
  // 加入监听 然后读写；
  FD_ZERO(&rdset);
  FD_ZERO(&monitorSet);
  FD_SET(sfd, &monitorSet);
  FD_SET(STDIN_FILENO, &monitorSet);
  int netfd[10] = {0};
  int curConn = 0;
  // 实现聊天室功能 服务器不在监听标准输入 服务器功能：处理新的客户端 监听netFd//处理客户端发送的消息转发 维护netfd 的数组后进行转发；
  while (1)
  {
    memcpy(&rdset, &monitorSet, sizeof(fd_set)); //
    int ret = select(20, &rdset, NULL, NULL, NULL);
    ERROR_CHECK(ret, -1, "select");
    if (FD_ISSET(sfd, &rdset))
    {
      netfd[curConn] = accept(sfd, NULL, NULL);
      ERROR_CHECK(netfd[curConn], -1, "accept");
      FD_SET(netfd[curConn], &monitorSet);
      puts("new connect is accepted!\n");
      ++curConn;
    }

    for (int i = 0; i < curConn; i++)
    {
      if(FD_ISSET(netfd[i],&rdset))
      {
        bzero(buf, sizeof(buf));
        recv(netfd[i], buf, sizeof(buf), 0);
        for (int j = 0; j < curConn; ++j)
        {
          if (j == i)
          {
            continue;
          }
          send(netfd[j], buf, strlen(buf), 0);
        }
      }
    }
  }
    

    return 0;
  }